home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
- /* This gives us NewRoutineDescriptor and NewFatRoutineDescriptor traps. */
- #define USESROUTINEDESCRIPTORS 1
-
- #include <Types.h>
- #include <Memory.h>
- #include <MixedMode.h>
- #include <Traps.h>
- #include <Resources.h>
- #include <ToolUtils.h>
- #include <Processes.h>
- #include <FragLoad.h>
- #include <GestaltEqu.h>
- #include "emacs-version.h"
- #include "kbd-patch-data.h"
-
- /* To make sure we use the powerPC versions of the patch. */
- #define TEST_POWERPC_CODE 0
-
- int patch_contigous_long(Ptr,long);
- int patch_split_long(Ptr,long);
-
- typedef struct {
- ProcPtr code;
- Ptr toc;
- } transition_vector;
-
- void
- install(void)
- {
- int err;
- THz old_zone;
- char have_powerPC;
- long response;
- struct keyboard_patch_data *kbpd;
- Handle KeyTrans_patch,gestalt_dispatch;
- UniversalProcPtr KeyTrans_patch_upp,gestalt_dispatch_upp;
- transition_vector *powerPC_KeyTrans_patch,*powerPC_gestalt_dispatch;
-
- /* Do nothing for an old system. Emacs won't run on it. */
- err = Gestalt(gestaltSystemVersion,&response);
- if (err || LoWord(response) < 0x0700) return;
-
- /* We need some global data */
- kbpd = (struct keyboard_patch_data *)NewPtrSys(sizeof(struct keyboard_patch_data));
- kbpd->version = emacs_version_complete;
- kbpd->original = NGetTrapAddress(_KeyTrans,ToolTrap);
- kbpd->emacs_psn.lowLongOfPSN = kbpd->emacs_psn.highLongOfPSN = 0;
-
- /* Get the patch and gestalt code. They must go into the system heap. */
- KeyTrans_patch = GetResource('CODE',128);
- if (KeyTrans_patch == 0L) return;
- DetachResource(KeyTrans_patch);
- if (ResError()) return;
- HLock(KeyTrans_patch);
- err = patch_contiguous_long(*KeyTrans_patch,(long)kbpd);
- if (err) return;
-
- gestalt_dispatch = GetResource('CODE',129);
- if (gestalt_dispatch == 0L) return;
- DetachResource(gestalt_dispatch);
- if (ResError()) return;
- HLock(gestalt_dispatch);
- err = patch_contiguous_long(*gestalt_dispatch,(long)kbpd);
- if (err) return;
-
- /* If we have powerPC, install fat routine descriptors instead of ProcPtrs. */
- err = Gestalt(gestaltSysArchitecture,&response);
- have_powerPC = !err && (response == gestaltPowerPC);
- if (have_powerPC) {
- err = load_powerPC_code(&powerPC_KeyTrans_patch,&powerPC_gestalt_dispatch);
- if (err) have_powerPC = 0;
- err = patch_split_long((Ptr)powerPC_KeyTrans_patch->code,(long)kbpd);
- if (err) have_powerPC = 0;
- err = patch_split_long((Ptr)powerPC_gestalt_dispatch->code,(long)kbpd);
- if (err) have_powerPC = 0;
- }
-
- /* Create the UPP's in the system heap. */
-
- if (have_powerPC) {
- old_zone = GetZone();
- SetZone(SystemZone());
-
- #if TEST_POWERPC_CODE
- KeyTrans_patch_upp =
- NewRoutineDescriptor((ProcPtr)powerPC_KeyTrans_patch,
- uppKeyTransProcInfo,
- kPowerPCISA);
- gestalt_dispatch_upp =
- NewRoutineDescriptor((ProcPtr)powerPC_gestalt_dispatch,
- uppSelectorFunctionProcInfo,
- kPowerPCISA);
- #else
- KeyTrans_patch_upp =
- NewFatRoutineDescriptor((ProcPtr)*KeyTrans_patch,
- (ProcPtr)powerPC_KeyTrans_patch,
- uppKeyTransProcInfo);
- gestalt_dispatch_upp =
- NewFatRoutineDescriptor((ProcPtr)*gestalt_dispatch,
- (ProcPtr)powerPC_gestalt_dispatch,
- uppSelectorFunctionProcInfo);
- #endif
-
- SetZone(old_zone);
- }
- else {
- KeyTrans_patch_upp = (UniversalProcPtr)*KeyTrans_patch;
- gestalt_dispatch_upp = (UniversalProcPtr)*gestalt_dispatch;
- }
-
- /* Commit the patch. */
- NSetTrapAddress(KeyTrans_patch_upp,_KeyTrans,ToolTrap);
-
- /* Install a hook so that Emacs when launched can install its data for the patch. */
- err = NewGestalt('EMAc',gestalt_dispatch_upp);
- }
-
- int
- patch_contiguous_long(Ptr h,long replacement)
- {
- long i;
- short *q = (short *)h;
-
- for (i = 0; i<20; ++i) {
- if (*(long *)&q[i] == PATCH_MAGIC) {
- *(long *)&q[i] = replacement;
- return 0;
- }
- }
-
- return -1;
- }
-
- int
- patch_split_long(Ptr h,long replacement)
- {
- long i;
- short *q = (short *)h;
-
- for (i = 0; i<20; ++i) {
- if (q[i] == HiWord(PATCH_MAGIC) && q[i+2] == LoWord(PATCH_MAGIC)) {
- q[i] = HiWord(replacement);
- q[i+2] = LoWord(replacement);
- return 0;
- }
- }
-
- return -1;
- }
-
- int
- load_powerPC_code(transition_vector **text_code,transition_vector **gestalt_code)
- {
- int err;
- long size;
- Ptr mainAddr;
- SymClass symClass;
- Handle powerPC_code;
- ConnectionID connID;
- unsigned char errName[256],s[256];
-
- powerPC_code = GetResource('CODE',130);
- if (powerPC_code == 0L) return -1;
- DetachResource(powerPC_code);
- if (ResError()) return -1;
- size = GetHandleSize(powerPC_code);
- if (MemError()) return -1;
- HLock(powerPC_code);
-
- GetIndString(s,128,1);
- err = GetMemFragment(*powerPC_code,size,s,
- kLoadLib,&connID,&mainAddr,errName);
- if (err) return -1;
-
- GetIndString(s,128,2);
- err = FindSymbol(connID,s,(Ptr *)text_code,&symClass);
- if (err) return -1;
-
- GetIndString(s,128,3);
- err = FindSymbol(connID,s,(Ptr *)gestalt_code,&symClass);
- if (err) return -1;
-
- return 0;
- }
-